/*
 * @lc app=leetcode.cn id=1114 lang=cpp
 *
 * [1114] 按序打印
 */
#include "include.h"
// @lc code=start
class Foo {
public:
    Foo() {
        state_ = 0;
    }

    void first(function<void()> printFirst) {
        while (1){
            std::lock_guard lockGuard(lock_);

            if (state_ == 0){
                // printFirst() outputs "first". Do not change or remove this line.
                printFirst();
                state_ = 1;
                break;
            }
        }
    }

    void second(function<void()> printSecond) {
        while (1){
            std::lock_guard lockGuard(lock_);

            if (state_ == 1){
                // printFirst() outputs "first". Do not change or remove this line.
                printSecond();
                state_ = 2;
                break;
            }
        }
    }

    void third(function<void()> printThird) {
        while (1){
            std::lock_guard lockGuard(lock_);

            if (state_ == 2){
                // printFirst() outputs "first". Do not change or remove this line.
                printThird();
                state_ = 3;
                break;
            }
        }
    }
private:
    std::mutex lock_;
    int state_;
};
// @lc code=end

void first(function<void()> printFirst) {

	// printFirst() outputs "first". Do not change or remove this line.
	printFirst();
	unique_lock<mutex> lock(m_mutex);
	m_index = 2;
	m_cond.notify_all();
}

void second(function<void()> printSecond) {

	// printSecond() outputs "second". Do not change or remove this line.
	
	unique_lock<mutex> lock(m_mutex);
	m_cond.wait(lock, [this]{return this->index() == 2; });
	m_index = 3;
	printSecond();
	m_cond.notify_one();
}

void third(function<void()> printThird) {

	// printThird() outputs "third". Do not change or remove this line.

	unique_lock<mutex> lock(m_mutex);
	m_cond.wait(lock, [this]{return this->index() == 3; });
	printThird();
}

int index(){ return m_index; }

private: int m_index; mutex m_mutex; condition_variable m_cond;